package demo2;


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;

import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.apache.tools.zip.ZipOutputStream;

/**
* file zip compress
* 采用org.apache.tools.zip来进行zip包的解压缩，支持目录嵌套和中文名
* @author z278440337  05/12/09
*
*/
public class ZipCompressor {
  public static final String rootpath="E:\\zip";
  public static final String destinct="E:\\xml";
  public static final int BUFFER = 2048;
  
  /**
   * @param args
   */
  public static void main(String[] args) throws Exception{
      
      zip(destinct+"\\test\\fundmostfinancetarget\\reportsource.xml",destinct+"\\test\\fundmostfinancetarget.zip");
  }
  
  /** 
   * 压缩文件
   * @param source 源路径,可以是文件,也可以目录
   * @param destinct  目标路径,压缩文件名
   * @throws IOException,FileNotFoundException
   */ 
  public static void zip(String source, String destinct) throws IOException, FileNotFoundException  {
      File file = new File(source);
      ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream((new FileOutputStream(destinct))));
      
      // 压缩目录和文件
      if(file.isDirectory()) {
          compressFile(file,zos,"");
      } else {
          compressFile(file,zos,file.getName());
      }
      
      zos.close();
  }
  
  /** 
   * 递归压缩文件
   * @param source 源路径,可以是文件,也可以目录
   * @param destinct  目标路径,压缩文件名
   * @param base 目录
   * @throws IOException,FileNotFoundException
   */ 
  public static void compressFile(File file, ZipOutputStream zos, String base) throws IOException, FileNotFoundException  {
      if(file.isDirectory()) {
          File[] innerFile = file.listFiles();
          if(innerFile != null) {
              zos.putNextEntry(new ZipEntry(base+"/"));
              base = base.length() == 0 ?"":base+"/";
              for(int i = 0; i<innerFile.length; i++) {
                  compressFile(innerFile[i],zos,base+innerFile[i].getName());
              }
          }
          
      } else {
          byte[] buf = new byte[BUFFER];
          int len;
          ZipEntry entry = new ZipEntry(base);
          FileInputStream fin = new FileInputStream(file);
          BufferedInputStream in = new BufferedInputStream(fin);
          zos.putNextEntry(entry);
          while(( len = in.read(buf)) >=0) {
              zos.write(buf);
          }
          in.close();
          zos.closeEntry();
          
      }
  }
  
  /** 
   * 解压缩文件
   * @param source 源路径,可以是文件,也可以目录
   * @param destinct  目标路径,压缩文件名
   * @throws IOException,FileNotFoundException
   */ 
  public static void unzip(String source, String destinct) throws IOException, FileNotFoundException  {
      ZipFile zipFile = new ZipFile(source);
      Enumeration enm = zipFile.getEntries();
      ZipEntry entry = null;
      while(enm.hasMoreElements()) {
          entry = (ZipEntry) enm.nextElement();
          if(entry.isDirectory()) {
              String name = entry.getName().trim();
              name = name.substring(0,name.length()-1);
              mkDirs(destinct+File.separator+name);
          } else {
              String name = entry.getName();
              if(name.lastIndexOf("/") != -1) {
                  String dir = name.substring(0,name.lastIndexOf("/"));
                  mkDirs(destinct+File.separator+dir);
              }
              File file = new File(destinct+File.separator+entry.getName());
              file.createNewFile();
              InputStream  in = zipFile.getInputStream(entry);
              FileOutputStream out = new FileOutputStream(file);
              int len ;
              byte[] buf = new byte[BUFFER];
              while((len=in.read(buf)) != -1) {
                  out.write(buf,0,len);
              }
              out.close();
              in.close();
          }
      }
  }
  
  /**
   * 创建目录包括子目录
   * @param dir
   * @throws Exception
   */
  public static void mkDirs(String dir) throws IOException, FileNotFoundException {
      if(dir == null || "".equals(dir)) {
          return;
      }
      File file = new File(dir);
      if(!file.exists()) {
          file.mkdirs();
      }
  }
  
  /** 
   * 单级目录，递归解压文件
   * @param source 源路径,可以是文件,也可以目录
   * @param destinct  目标路径,压缩文件名
   * @throws IOException
   */ 
  public static void decompressSingleDirectory(String source, String destinct) throws IOException {
      ZipFile zipFile = new ZipFile(source);
      Enumeration emu = zipFile.getEntries();
      
      while (emu.hasMoreElements()) {
          ZipEntry entry = (ZipEntry) emu.nextElement();
          while(entry.isDirectory()) {
              new File(destinct+entry.getName()).mkdirs();
              continue;
          }
          
          BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));
          File file = new File(destinct + entry.getName());
          //加入这个的原因是zipfile读取文件是随机读取的，这就造成可能先读取一个文件
          //而这个文件所在的目录还没有出现过，所以要建出目录来。
          File parent = file.getParentFile();
          if(parent != null && !parent.exists()) {
              parent.mkdirs();
          }
          
          FileOutputStream fos = new FileOutputStream(file);
          
          BufferedOutputStream bos = new BufferedOutputStream(fos, BUFFER);
          int count = 0;
          byte data[] = new byte[BUFFER];
          while((count = bis.read(data, 0 ,BUFFER)) != -1) {
              bos.write(data,0,count);
          }
          bos.flush();
          bos.close();
          bis.close();
      }
      zipFile.close();
  }
}
